(function (window) {
  const PENDING = 'pending';
  const RESOLVED = 'resolved';
  const REJECTED = 'rejected';

  class Promise {
      /* 
    Promise：构造函数
    excutor: 执行器
    */
    constructor(excutor) {
      const _this = this;
      _this.status = PENDING; // 状态
      _this.data = undefined;  // 数据
      _this.callbacks = [];  // 保存回调函数，结构：{onResolved() {}, onReject() {}}
      function resolve(value) {
        // 当前状态不是pending结束
        if (_this.status !== PENDING) {
          return
        }
        // 修改状态
        _this.status = RESOLVED;
        // 保存数据
        _this.data = value;
        // 立即执行callback
        if (_this.callbacks.length > 0) {
          _this.callbacks.forEach(callbacksObj => {
            setTimeout(() => {  // 异步执行回调
              callbacksObj.onResolved(value)
            }, 0)
          });
        }

      }

      function reject(reason) {
        // 当前状态不是pending结束
        if (_this.status !== PENDING) {
          return
        }
        // 修改状态
        _this.status = REJECTED;
        // 保存数据
        _this.data = value;
        // 立即执行callback
        if (_this.callbacks.length > 0) {
          _this.callbacks.forEach(callbacksObj => {
            setTimeout(() => {  // 异步执行回调
              callbacksObj.onRejected(reason)
            }, 0)
          });
        }
      }
      // 立即执行excutor
      try {
        excutor(resolve, reject);
      } catch (error) { // 抛出异常变为rejected
        reject(error);
      }
    }


    /* 
    Promise 原型对象.then
    指定成功和失败的回调函数
    返回一个新的Promise
    */
    then (onResolved, onRejected) {
      onResolved = typeof onResolved === 'function' ? onResolved : value => value

      onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

      const _this = this;
      // 返回一个新的promise
      return new Promise((resolve, reject) => {
        // 指定调用回调函数
        function handle(callback) {
          try {
            const result = callback(_this.data);
            if (result instanceof Promise) {  // 类型为promise，结果是这个promise的结果
              // result.then(
              //   value => resolve(value),
              //   reason => reject(reason)
              // )
              result.then(resolve, reject);
            } else {
              resolve(result);  // 非promise返回结果
            }
          } catch (error) { // 抛出异常，失败
            reject(error);
          }
        }

        if (_this.status === PENDING) {
          _this.callbacks.push({
            onResolved(value) {
              handle(onResolved)
            },
            onRejected(reason) {
              handle(onRejected)
            }
          })
        } else if (_this.status === RESOLVED) {
          setTimeout(() => {
            handle(onResolved)
          })
        } else {
          setTimeout(() => {
            handle(onRejected)
          })
        }
      })

    }

    /*
    Promise 原型对象.catch
    指定失败的回调函数
    返回一个新的Promise
    */
    catch (onRejected) {
      return this.then(undefined, onRejected)
    }

    /*
    Promise 原型对象.resolve
    返回一个指定value的Promise
    */
    static resolve = function (value) {
      // 返回一个成功/失败的promise
      return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
          value.then(resolve, reject)
        } else {
          resolve(value)
        }
      })
    }

    /*
    Promise 原型对象.reject
    返回一个指定reason的Promise
    */
    static reject = function (reason) {
      // 返回一个失败的promise
      return new Promise((resolve, reject) => {
        reject(reason);
      })
    }

    /*
    Promise 原型对象.all
    返回一个Promise，所有promise都成功才成功，一个失败就失败
    */
    static all = function (promises) {
      const values = new Array(promises.length);  // 保存所有成功的value
      let resolveCount = 0;  // 计数器，计算成功的数量
      return new Promise((resolve, reject) => {
        // 获取每个promise的结果
        promises.forEach((p, index) => {
          p.then(
            value => {
              resolveCount++;
              values[index] = value;
              if (resolveCount === promises.length) { // 所有都完成才会resolve
                resolve(values)
              }
            }, reason => {
              reject(reason)
            }
          )
        })
      })
    }

    /*
    Promise 原型对象.race
    返回一个Promise，由第一个完成的promise决定
    */
    static race = function (promises) {
      return new Promise((resolve, reject) => {
        promises.forEach((p) => {
          p.then(
            value => {
              resolve(value)
            }, reason => {
              reject(reason)
            }
          )
        })
      })
    }

  }
  // 暴露Promise
  window.Promise = Promise;
})(window)
